package com.xmut.mall.member.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmut.mall.member.dao.MemberCartDao;
import com.xmut.mall.member.entity.MemberCartEntity;
import com.xmut.mall.member.entity.MemberCouponEntity;
import com.xmut.mall.member.feign.CouponFeignService;
import com.xmut.mall.member.feign.WareFeignService;
import com.xmut.mall.member.service.MemberCartService;
import com.xmut.mall.member.service.MemberCouponService;
import com.xmut.mall.member.utils.RespBean;
import com.xmut.mall.member.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service("memberCartService")
public class MemberCartServiceImpl extends ServiceImpl<MemberCartDao, MemberCartEntity> implements MemberCartService {

    @Autowired
    private CouponFeignService couponFeignService;

    @Autowired
    private WareFeignService wareFeignService;

    @Autowired
    private MemberCouponService memberCouponService;



    /**
     * 添加购物车
     *
     * @param entity
     * @return
     */
//    @Caching(
//            evict = {@CacheEvict(value = "UserCart", key = "#entity.memberId"),
//                    @CacheEvict(value = "UserCartCount", key = "#entity.memberId")})
    @Override
    public RespBean addCart(MemberCartEntity entity) {
        // 前置检查 是否已经添加了购物车
        MemberCartEntity cartEntity = this.getOne(new QueryWrapper<MemberCartEntity>()
                .eq("member_id", entity.getMemberId())
                .eq("sku_id", entity.getSkuId()));

        if (cartEntity != null) {
            // 如果已经收藏过了 那就增加数量
            // 计算现在应该是多少件
            Long count = entity.getProductCount() + cartEntity.getProductCount();
            boolean update = this.update(new UpdateWrapper<MemberCartEntity>()
                    .set("product_count", count)
                    .eq("id", cartEntity.getId()));
            if (update) {
                return RespBean.success("添加成功");
            } else {
                return RespBean.error("添加失败，请稍后重试");
            }
        }

        // 如果没有收藏过
        entity.setCreateTime(new Date());
        boolean save = this.save(entity);
        if (save) {
            return RespBean.success("添加成功");
        } else {
            return RespBean.error("添加失败，请稍后重试");
        }
    }

    /**
     * 根据用户Id获取该用户的购物车列表
     *
     * @param memberId
     * @return
     */
//    @Cacheable(value = "UserCart", key = "#root.args[0]")
    @Override
    public List<MemberCartEntity> getCart(Long memberId) {
        return this.list(new QueryWrapper<MemberCartEntity>().eq("member_id", memberId));
    }

    /**
     * 获取购物车数量
     *
     * @param memberId
     * @return
     */
//    @Cacheable(value = "UserCartCount", key = "#root.args[0]")
    @Override
    public Integer cartCount(Long memberId) {
        return this.count(new QueryWrapper<MemberCartEntity>().eq("member_id", memberId));

    }

    /**
     * 删除购物车的商品
     *
     * @param memberId
     * @param skuId
     * @return
     */
//    @Caching(
//            evict = {@CacheEvict(value = "UserCart", key = "#memberId"),
//                    @CacheEvict(value = "UserCartCount", key = "#memberId")})
    @Override
    public RespBean deleteCartItem(Long memberId, Long skuId) {
        boolean remove = this.remove(new QueryWrapper<MemberCartEntity>().eq("member_id", memberId).eq("sku_id", skuId));
        if (remove) {
            return RespBean.success("删除成功");
        } else {
            return RespBean.error("删除失败");
        }
    }

    /**
     * 购物车详情页
     *
     * @param userInfo
     * @return
     */
    @Override
    public List<CartVo> goCart(Long userInfo) {
        // 先查出全部该用户收藏的购物车商品
        List<MemberCartEntity> carList = this.list(new QueryWrapper<MemberCartEntity>().eq("member_id", userInfo));

        // 分隔不同的店铺
        List<Long> storeIds = carList.stream().map(MemberCartEntity::getStoreId).distinct().collect(Collectors.toList());

        List<CartVo> list = storeIds.stream().map(storeId -> {
            // 要返回的vo
            CartVo vo = new CartVo();
            vo.setStoreId(storeId);
            vo.setStoreName(carList.get(0).getStoreName());
            vo.setCheckStatus(false);
            // 设置每个店铺的优惠券;
            RespBean cartShopCoupon = couponFeignService.getCartShopCoupon(storeId);
            if (cartShopCoupon.getCode() == 201) {
                List<CouponEntityVo> couponEntityVos = JSON.parseObject(JSON.toJSONString(cartShopCoupon.getObj()), new TypeReference<List<CouponEntityVo>>() {
                });
                vo.setCouponList(couponEntityVos);
            }

            // 去该用户的全部收藏数据里面找出匹配名和当前循环一致的 并且将其转换为MemberCartVo
            List<MemberCartVo> collect = carList.stream().filter(f -> {
                // 过滤出全部购物车商品中商铺id和当前循环的商铺id一致的商铺
                return f.getStoreId().equals(storeId);
            }).map(item -> {
                // 把商铺id一致的购物车商铺转换为MemberCartVo
                MemberCartVo memberCartVo = new MemberCartVo();
                // 属性对拷
                BeanUtils.copyProperties(item, memberCartVo);
                // 获取该商品的库存数量
                RespBean skuWareNumberResp = wareFeignService.getSkuWareNumber(item.getSkuId());
                if (skuWareNumberResp.getCode() == 201) {
                    Integer carItemWareNum = JSON.parseObject(JSON.toJSONString(skuWareNumberResp.getObj()), Integer.class);
                    memberCartVo.setQuantity(carItemWareNum);
                }
                // 计算每一项的小计 商品数量 * 单价（如果有优惠券还要另外算 这里先这样）
                memberCartVo.setSubTotal(new BigDecimal(item.getProductCount()).multiply(item.getSkuPrice()));
                return memberCartVo;
            }).collect(Collectors.toList());
            vo.setCatList(collect);
            return vo;
        }).collect(Collectors.toList());

        return list;
    }

    /**
     * 购物车操作 全选
     *
     * @param memberId
     * @return
     */
    @Override
    public RespBean checkAll(Long memberId, Long check) {
        boolean update = this.update(new UpdateWrapper<MemberCartEntity>()
                .set("check_status", check)
                .eq("member_id", memberId));
        if (update) {
            return RespBean.success("修改成功");
        } else {
            return RespBean.error("修改失败");
        }
    }

    /**
     * 购物车操作全选 根据商铺
     *
     * @return
     */
    @Override
    public RespBean checkAllByStore(Map<String, Object> params) {
        Long memberId = MapUtil.getLong(params, "memberId");
        Integer check = MapUtil.getInt(params, "check");
        Long storeId = MapUtil.getLong(params, "storeId");

        boolean update = this.update(new UpdateWrapper<MemberCartEntity>()
                .set("check_status", check)
                .eq("member_id", memberId)
                .eq("store_id", storeId));
        if (update){
            return RespBean.success("修改成功");
        }else {
            return RespBean.error("修改失败");
        }

    }

    /**
     * 购物车操作 选中或取消单个商品
     *
     * @param params
     * @return
     */
    @Override
    public RespBean checkSingleItem(Map<String, Object> params) {
        boolean update = this.update(new UpdateWrapper<MemberCartEntity>()
                .set("check_status", params.get("check"))
                .eq("member_id", params.get("memberId"))
                .eq("sku_id", params.get("skuId")));
        if (update) {
            return RespBean.success("修改成功");
        } else {
            return RespBean.error("修改失败");
        }
    }

    /**
     * 改变购物车项选中的数量
     *
     * @param params
     * @return
     */
    @Override
    public RespBean changeCartItemNum(Map<String, Object> params) {
        boolean update = this.update(new UpdateWrapper<MemberCartEntity>()
                .set("product_count", params.get("val"))
                .eq("member_id", params.get("memberId"))
                .eq("sku_id", params.get("skuId")));
        if (update) {
            return RespBean.success("修改成功");
        } else {
            return RespBean.error("修改失败");
        }
    }

    /**
     * 根据map删除购物车之中的项
     *
     * @param params
     * @return
     */
    @Override
    public RespBean deleteCartItemByMap(Map<String, Object> params) {
        List<String> ids = Arrays.asList(params.get("ids").toString().split(","));
        boolean remove = this.remove(new QueryWrapper<MemberCartEntity>()
                .eq("member_id", params.get("memberId"))
                .in("sku_id", ids));
        if (remove) {
            return RespBean.success("删除成功");
        } else {
            return RespBean.error("删除失败");
        }
    }

    /**
     * 清空购物车
     *
     * @param memberId
     * @return
     */
    @Override
    public RespBean clearCart(Long memberId) {
        boolean result = this.remove(new QueryWrapper<MemberCartEntity>().eq("member_id", memberId));
        if (result) {
            return RespBean.success("清空购物车成功");
        } else {
            return RespBean.error("清空购物车失败");
        }

    }

    /**
     * 获取当前购物车的结算信息
     *
     * @param memberId
     * @return
     */
    @Override
    public RespBean getCartPriceDetail(Long memberId) {
        // 先查出当前用户的全部购物车项
        List<MemberCartEntity> cartList = this.list(new QueryWrapper<MemberCartEntity>().eq("member_id", memberId));
        if (cartList == null) {
            // 当前购物车是空直接返回0
            PriceDetailVo priceDetailVo = new PriceDetailVo();
            priceDetailVo.setDiscountPrice(new BigDecimal(0));
            priceDetailVo.setFlowPrice(new BigDecimal(0));
            return RespBean.success("获取成功", priceDetailVo);
        }
        // 当前购物车不是空才进行计算
        // 过滤出当前被选中的项
        List<MemberCartEntity> filterList = cartList.stream().filter(f -> {
            return f.getCheckStatus() == true;
        }).collect(Collectors.toList());

        System.out.println("测试:" + filterList);

        PriceDetailVo priceDetailVo = new PriceDetailVo();
        priceDetailVo.setFlowPrice(new BigDecimal(0));


        for (MemberCartEntity item : filterList) {
            // 当前的被选中商品的数量
            BigDecimal count = new BigDecimal(item.getProductCount());
            // 计算总价
            BigDecimal total = count.multiply(item.getSkuPrice());
            // 累加
            priceDetailVo.setFlowPrice(priceDetailVo.getFlowPrice().add(total));
            // 折扣系统暂未完善 先默认给个0
            priceDetailVo.setDiscountPrice(new BigDecimal(0));
        }

        return RespBean.success("获取成功", priceDetailVo);

    }

    /**
     * 获取商品结算详情(购物车方式进行结算)
     * @param params
     * @return
     */
    @Override
    public RespBean getGoodPayDetailTypeCART(Map<String, Object> params) {
        PayDetailVo payDetailVo = new PayDetailVo();
        Long userId = MapUtil.getLong(params, "userId");
        List<Long> useChooseCouponIDS = MapUtil.get(params, "useCouponList", new cn.hutool.core.lang.TypeReference<List<Long>>() {
        });
        // 如果是null就转化为空集合
        if (CollUtil.isEmpty(useChooseCouponIDS)) {
            useChooseCouponIDS = new ArrayList<>();
        }
        // 获取当前被选中的购物车项(因为选中与否是数据库控制的 前端只负责渲染没有负责存储选中项)
        List<MemberCartEntity> cartList = this.list(new QueryWrapper<MemberCartEntity>()
                .eq("check_status", 1)
                .eq("member_id", userId));
        // 将不同的店铺分成list
        List<Long> storeIds = cartList.stream().map(MemberCartEntity::getStoreId).distinct().collect(Collectors.toList());
        List<CartVo> list = storeIds.stream().map(storeId -> {
            // 要返回的vo
            CartVo vo = new CartVo();
            vo.setStoreId(storeId);
            vo.setStoreName(cartList.get(0).getStoreName());
            vo.setCheckStatus(false);
            // 设置每个店铺的优惠券;
            vo.setCouponList(new ArrayList<>());
            // 去该用户的全部收藏数据里面找出匹配名和当前循环一致的 并且将其转换为MemberCartVo
            List<MemberCartVo> collect = cartList.stream().filter(f -> {
                // 过滤出全部购物车商品中商铺id和当前循环的商铺id一致的商铺
                return f.getStoreId().equals(storeId);
            }).map(item -> {
                // 把商铺id一致的购物车商铺转换为MemberCartVo
                MemberCartVo memberCartVo = new MemberCartVo();
                // 属性对拷
                BeanUtils.copyProperties(item, memberCartVo);
                // 获取该商品的库存数量
                RespBean skuWareNumberResp = wareFeignService.getSkuWareNumber(item.getSkuId());
                if (skuWareNumberResp.getCode() == 201) {
                    Integer carItemWareNum = JSON.parseObject(JSON.toJSONString(skuWareNumberResp.getObj()), Integer.class);
                    memberCartVo.setQuantity(carItemWareNum);
                }
                // 计算每一项的小计 商品数量 * 单价（如果有优惠券还要另外算 这里先这样）
                memberCartVo.setSubTotal(new BigDecimal(item.getProductCount()).multiply(item.getSkuPrice()));
                return memberCartVo;
            }).collect(Collectors.toList());
            vo.setCatList(collect);
            return vo;
        }).collect(Collectors.toList());
        payDetailVo.setCheckedSkuList(list);
        payDetailVo.setCartList(list);

        // 获取当前可用的优惠券
        List<MemberCouponEntity> userAllCanUseCouponByCART = memberCouponService.getUserAllCanUseCouponByCART(cartList);
        payDetailVo.setCanUseCoupons(userAllCanUseCouponByCART);

        /**
         * 过滤出用户选择了的可用的优惠券
         */
        List<MemberCouponEntity> countCouponList = new ArrayList<>();
        for (MemberCouponEntity entity : userAllCanUseCouponByCART) {
            for (Long useChooseCouponID : useChooseCouponIDS) {
                if (useChooseCouponID.equals(entity.getCouponId())){
                    countCouponList.add(entity);
                }
            }
        }
        // 计算价格
        PriceDetailDTO priceDetailDTO = new PriceDetailDTO();
        BigDecimal originalPrice = BigDecimal.ZERO;
        for (MemberCartEntity memberCartEntity : cartList) {
            // 把购物车的物品的价格加起来
            originalPrice = originalPrice.add(memberCartEntity.getSkuPrice());
        }
        priceDetailDTO.setOriginalPrice(originalPrice); // 原始价格
        priceDetailDTO.setGoodsPrice(originalPrice);// 商品总金额（商品原价）
        BigDecimal freightPrice = BigDecimal.ZERO;
        payDetailVo.setPriceDetailDTO(priceDetailDTO);
        priceDetailDTO.setFreightPrice(freightPrice); // 配送费 本功能还未做 先空着
        BigDecimal couponReducePrice = BigDecimal.ZERO;
        // 计算优惠券扣掉的金额
        for (MemberCouponEntity entity : countCouponList) {
            // 如果是满减类型
            if (entity.getCouponType().equals("PRICE")){
                // 判断是优惠券是否满足使用门槛
                if (originalPrice.compareTo(entity.getConsumeThreshold())==1){
                    couponReducePrice = couponReducePrice.add(entity.getPrice());
                }
            }
            // 如果优惠券是满减类型
            if (entity.getCouponType().equals("DISCOUNT")) {
                // 将最早的总价拿来然后计算折数
                if (originalPrice.compareTo(entity.getConsumeThreshold())==1){
                    BigDecimal discount = entity.getDiscount().multiply(new BigDecimal("0.1"));
                    BigDecimal disCountNum = originalPrice.subtract(originalPrice.multiply(discount));
                    couponReducePrice = couponReducePrice.add(disCountNum);
                }
            }
        }
        priceDetailDTO.setCouponPrice(couponReducePrice);// 优惠券减掉钱

        // 查询现在可用的满减活动
        List<Long> skuIds = cartList.stream().map(MemberCartEntity::getSkuId).collect(Collectors.toList());
        RespBean cartCheckFullDiscountResp = couponFeignService.getCartCheckFullDiscount(skuIds);
        List<FullDiscountEntityVo> fullDiscountList= JSON.parseObject(JSON.toJSONString(cartCheckFullDiscountResp.getObj()), new TypeReference<List<FullDiscountEntityVo>>() {
        });
        // 防止为空指针异常
        if (CollUtil.isEmpty(fullDiscountList)){
            fullDiscountList = new ArrayList<>();
        }
        BigDecimal fullDiscountReducePrice = BigDecimal.ZERO;// 满减活动减掉的价格
        for (FullDiscountEntityVo fullDiscountEntityVo : fullDiscountList) {
            // 如果是减现金
            if (fullDiscountEntityVo.getFullMinusFlag()) {
                if (originalPrice.compareTo(fullDiscountEntityVo.getFullMoney()) == 1) {
                    fullDiscountReducePrice = fullDiscountReducePrice.add(fullDiscountEntityVo.getFullMinus());
                }
            } else {
                // 是满折
                if (originalPrice.compareTo(fullDiscountEntityVo.getFullMoney()) == 1) {
                    BigDecimal discount = fullDiscountEntityVo.getFullRate().multiply(new BigDecimal("0.1"));
                    BigDecimal disCountNum = originalPrice.subtract(originalPrice.multiply(discount));
                    fullDiscountReducePrice = fullDiscountReducePrice.add(disCountNum);
                }
            }
        }
        priceDetailDTO.setDiscountPrice(fullDiscountReducePrice); // 满减减掉的金额
        BigDecimal totalReduce = fullDiscountReducePrice.add(couponReducePrice); // 现在全部减掉的金额
        BigDecimal flowPrice = originalPrice.subtract(totalReduce).subtract(freightPrice); // 最终订单价格 总价-全部优惠(满减+优惠券)-运费
        priceDetailDTO.setFlowPrice(flowPrice);
        // 计算数量
        Long num = 0L;
        for (MemberCartEntity memberCartEntity : cartList) {
            num+=memberCartEntity.getProductCount();
        }
        priceDetailDTO.setTotalNum(num);
        payDetailVo.setPriceDetailDTO(priceDetailDTO);
        return RespBean.success("获取成功",payDetailVo);
    }

    /**
     * 获取用户购物车中目前选中的购物车项的信息
     * @param params
     * @return
     */
    @Override
    public List<CartVo> getUserCheckedCartItem(Map<String, Object> params) {
        Long userId = MapUtil.getLong(params, "userId");
        // 先查出全部该用户收藏的购物车商品
        List<MemberCartEntity> carList = this.list(new QueryWrapper<MemberCartEntity>()
                .eq("check_status",1)
                .eq("member_id", userId));

        // 分隔不同的店铺
        List<Long> storeIds = carList.stream().map(MemberCartEntity::getStoreId).distinct().collect(Collectors.toList());

        List<CartVo> list = storeIds.stream().map(storeId -> {
            // 要返回的vo
            CartVo vo = new CartVo();
            vo.setStoreId(storeId);
            vo.setStoreName(carList.get(0).getStoreName());
            vo.setCheckStatus(false);
            // 设置每个店铺的优惠券;
//            RespBean cartShopCoupon = couponFeignService.getCartShopCoupon(storeId);
//            if (cartShopCoupon.getCode() == 201) {
//                List<CouponEntityVo> couponEntityVos = JSON.parseObject(JSON.toJSONString(cartShopCoupon.getObj()), new TypeReference<List<CouponEntityVo>>() {
//                });
//                vo.setCouponList(couponEntityVos);
//            }

            // 去该用户的全部收藏数据里面找出匹配名和当前循环一致的 并且将其转换为MemberCartVo
            List<MemberCartVo> collect = carList.stream().filter(f -> {
                // 过滤出全部购物车商品中商铺id和当前循环的商铺id一致的商铺
                return f.getStoreId().equals(storeId);
            }).map(item -> {
                // 把商铺id一致的购物车商铺转换为MemberCartVo
                MemberCartVo memberCartVo = new MemberCartVo();
                // 属性对拷
                BeanUtils.copyProperties(item, memberCartVo);
                // 获取该商品的库存数量
                RespBean skuWareNumberResp = wareFeignService.getSkuWareNumber(item.getSkuId());
                if (skuWareNumberResp.getCode() == 201) {
                    Integer carItemWareNum = JSON.parseObject(JSON.toJSONString(skuWareNumberResp.getObj()), Integer.class);
                    memberCartVo.setQuantity(carItemWareNum);
                }
                // 计算每一项的小计 商品数量 * 单价（如果有优惠券还要另外算 这里先这样）
                memberCartVo.setSubTotal(new BigDecimal(item.getProductCount()).multiply(item.getSkuPrice()));
                return memberCartVo;
            }).collect(Collectors.toList());
            vo.setCatList(collect);
            return vo;
        }).collect(Collectors.toList());

        return list;



    }

    /**
     * 获取用户购物车中进行结算的购物车项
     * @param userId
     * @return
     */
    @Override
    public List<MemberCartEntity> getUserCheckedCartEntityItem(Long userId) {
        List<MemberCartEntity> carList = this.list(new QueryWrapper<MemberCartEntity>()
                .eq("check_status",1)
                .eq("member_id", userId));
        return carList;
    }
}
